
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <iostream>
#include <map>
#include <vector>
#include "video_bbox_drawer.h"
#include "serialize.hpp"
#include "mock_detect_def.h"

#include <fstream> // std::ifstream

// ref: https://docs.opencv.org/3.4/db/d28/tutorial_cascade_classifier.html


int drawBBoxOnVideo(const char *inputVideo, const char *bboxStr, int bboxStrLen, const char *outputVideo)
{
    std::cout << " inputVideo: " << inputVideo << ", outputVideo: " << outputVideo << std::endl;
    // deserialize string
    std::istringstream is(std::string(bboxStr, bboxStrLen));
    TrajectoryInfo_t info;
    deserialize(is, info.video_name);
    deserialize(is, info.video_width);
    deserialize(is, info.video_height);
    deserialize(is, info.video_framerate);
    while (!is.eof() && is.tellg() != bboxStrLen)
    {
        Track_t track;
        deserialize(is, track);
        info.tracks.push_back(track);
        // std::cout << "track.f: " << track.f << std::endl;
    }
    std::cout << "info.video_name: " << info.video_name << std::endl;
    std::cout << "info.video_width: " << info.video_width << std::endl;
    std::cout << "info.video_height: " << info.video_height << std::endl;
    std::cout << "info.video_framerate: " << info.video_framerate << std::endl;
    std::cout << "info.tracks.size(): " << info.tracks.size() << std::endl;

    // open output video
    cv::VideoWriter outputVideoWriter;
    int fcc = cv::VideoWriter::fourcc('X', 'V', 'I', 'D');
    // int fcc = cv::VideoWriter::fourcc('a', 'v', 'c', '1');
    // int fcc = cv::VideoWriter::fourcc('M', 'J', 'P', 'G');
    outputVideoWriter.open(outputVideo, fcc, info.video_framerate, cv::Size(info.video_width, info.video_height));

    std::cout << " =========== " << std::endl;

    // open intput video
    cv::VideoCapture capture;
    capture.open(inputVideo);
    if (!capture.isOpened())
    {
        std::cout << "--(!)Error opening video capture, inputVideo: " << inputVideo << std::endl;
        return -1;
    }

    int index = 0;
    cv::Mat frame;
    while (capture.read(frame))
    {
        if (frame.empty())
        {
            std::cout << "--(!) No captured frame -- Break!\n";
            break;
        }
        auto it = std::find_if(info.tracks.begin(), info.tracks.end(), [&index](const Track_t &track){ return index == track.f; });
        if (it != info.tracks.end())
        {
            // draw
            auto & rect = it->rect;
            cv::Point center(rect.x + rect.w / 2, rect.y + rect.h / 2);
            cv::ellipse(frame, center, cv::Size(rect.w / 2, rect.h / 2), 0, 0, 360, cv::Scalar(255, 0, 255), 4);
        }
        // write output video
        outputVideoWriter.write(frame);
        index++;
    }
    outputVideoWriter.release();

    return 0;
}

int main()
{
    std::ifstream is("detect_result.txt", std::ifstream::binary); // open file
    std::ostringstream tmp;
    tmp << is.rdbuf();
    std::string str = tmp.str();
    const char *inputVideo = "face_1280_720.h264";
    const char *outputVideo = "face_1280_720_output.h264";
    drawBBoxOnVideo(inputVideo, str.c_str(), str.length(), outputVideo);
    return 0;
}
